﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Drawing;
using System.IO;
using System.Xml;
using System.Text;
using System.Windows.Forms;
using System.DirectoryServices;
using System.DirectoryServices.AccountManagement;

namespace CopyProp
{
    public partial class frmMain : Form
    {
        DirectoryEntry sourceObject = new DirectoryEntry();
        DirectoryEntry destinationObject = new DirectoryEntry();
        string configFile = Path.GetDirectoryName(Application.ExecutablePath) + "\\" + "Config.xml";

        public frmMain()
        {
            InitializeComponent();
            fillDomainListbox();
        }

        //Copy attributes from source to destionation object.
        private void copyAttributes()
        {
            string descriptionField = "";
            string locationField = "";
            bool conditionsmet = true;

            if (!cbDescription.Checked && !cbLocation.Checked && !cbGroupMembership.Checked)
            {
                tbBoxStatus.AppendText("Er is geen attribuut geselecteerd!" + Environment.NewLine +
                    "Selecteer tenminste één attribuut." + Environment.NewLine);
                conditionsmet = false;
            }
            else
            {
                // Check and find source object.
                if (validInput(tbCopyFrom.Text))
                {
                    sourceObject = getObject(tbCopyFrom.Text);
                    if (sourceObject != null)
                    {
                        tbBoxStatus.AppendText("Source object gevonden : " + sourceObject.Path +
                            Environment.NewLine);
                    }
                    else
                    {
                        tbBoxStatus.AppendText("Source object niet gevonden!" + Environment.NewLine);
                        conditionsmet = false;
                    }
                }
                else
                {
                    tbBoxStatus.AppendText("Geen geldig WS/LT nummer voor de source." + Environment.NewLine);
                    conditionsmet = false;
                }

                // Check and find destination object.
                if (validInput(tbCopyTo.Text))
                {
                    destinationObject = getObject(tbCopyTo.Text);
                    if (destinationObject != null)
                    {
                        tbBoxStatus.AppendText("Destination object gevonden : " + destinationObject.Path +
                            Environment.NewLine);
                    }
                    else
                    {
                        tbBoxStatus.AppendText("Destination object niet gevonden!" + Environment.NewLine);
                        conditionsmet = false;
                    }
                }
                else
                {
                    tbBoxStatus.AppendText("Geen geldig WS/LT nummer voor de destination." + Environment.NewLine);
                    conditionsmet = false;
                }

                if (conditionsmet == true)
                {
                    string message = "Alle gegevens zijn verzameld. Weet je zeker dat je door wilt gaan?";
                    string caption = "Doorgaan met kopieren";
                    MessageBoxButtons buttons = MessageBoxButtons.YesNo;
                    DialogResult answer;

                    // Displays the MessageBox.

                    answer = MessageBox.Show(message, caption, buttons);

                    if (answer == System.Windows.Forms.DialogResult.Yes)
                    {
                        if (cbDescription.Checked)
                        {
                            try
                            {
                                descriptionField = getDescription(sourceObject);
                                setDescription(descriptionField, destinationObject);
                                tbBoxStatus.AppendText("Description: '" + descriptionField +
                                    "' gekopieerd." + Environment.NewLine);
                            }
                            catch(Exception ex)
                            {
                                MessageBox.Show(ex.Message);
                            }
                        }

                        if (cbLocation.Checked)
                        {
                            try
                            {
                                locationField = getLocation(sourceObject);
                                setLocation(locationField, destinationObject);
                                tbBoxStatus.AppendText("Location: '" + locationField +
                                    "' gekopieerd." + Environment.NewLine);
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show(ex.Message);
                            }
                        }

                        if (cbGroupMembership.Checked)
                        {
                            try
                            {
                                tbBoxStatus.AppendText("Source groups:" + Environment.NewLine);
                                foreach (string path in getObjectGroups(sourceObject))
                                {
                                    if (addToGroup(path, destinationObject))
                                        tbBoxStatus.AppendText(path + " gekopieerd." + Environment.NewLine);
                                    else
                                        tbBoxStatus.AppendText(path + " niet gekopieerd!" + Environment.NewLine);
                                }
                            }
                            catch (Exception ex)
                            {
                                MessageBox.Show(ex.Message);
                            }
                        }
                    }
                    else
                    {
                        tbBoxStatus.AppendText("Kopieer actie afgebroken. Niets gekopieerd." + Environment.NewLine);
                    }
                }
            }
            tbBoxStatus.AppendText(Environment.NewLine);
        }

        // Validate input.
        // adObject may only contain characters and numbers
        private bool validInput(string adObject)
        {
             bool IsAlpha = false;
             if (System.Text.RegularExpressions.Regex.IsMatch(adObject, "^[a-zA-Z0-9_-]+$"))
             {
                IsAlpha = true;
             } else {
                IsAlpha = false;
             }
             return IsAlpha;
        }

        //Find and return directory object.
        // should be a computer object.
        private DirectoryEntry getObject(string adObject)
        {
            string ldapPath = "";
            DirectoryEntry de = null;
            SearchResult results = null;
            // set the ldap base, depending on the selected domain
            ldapPath = ldapString(comboBoxDomain.SelectedItem.ToString());
            de = new DirectoryEntry();
            de.Path = ldapPath;
            DirectorySearcher search = new DirectorySearcher(de);
            search.Filter = "(&(objectClass=computer)(cn=" + adObject + "))";
            search.PropertiesToLoad.Add("description");
            search.PropertiesToLoad.Add("location");
            search.PropertiesToLoad.Add("memberof");
            try
            {
                results = search.FindOne();
                if (results != null)
                {
                    search.Dispose();
                    return results.GetDirectoryEntry();
                }
                else
                {
                    return null;
                }
            }
            catch(Exception e)
            {
                MessageBox.Show(e.Message);
                return null;
            }
        }

        // Get descriptionfield. 
        // Return "" if null.
        private string getDescription(DirectoryEntry adObject)
        {
            if (adObject.Properties["Description"].Value != null)
            {
                return adObject.Properties["Description"].Value.ToString();
            }
            else
                return "";
        }

        // Get locationfield. 
        // Return "" if null.
        private string getLocation(DirectoryEntry adObject)
        {
            if (adObject.Properties["location"].Value != null)
            {
                return sourceObject.Properties["location"].Value.ToString();
            }
            else
                return "";
        }

        // Get groups the object is member of.
        // Return null if empty.
        private List<string> getObjectGroups(DirectoryEntry adObject)
        {
            int groupCount;
            List<string> groups = new List<string>();

            groupCount = adObject.Properties["memberOf"].Count;
            if (groupCount > 0)
            {
                foreach (string path in sourceObject.Properties["memberOf"])
                    groups.Add(path);
                return groups;
            }
            else
                return null;
        }

        // Set descriptionfield.
        private void setDescription(string descriptionField, DirectoryEntry adObject)
        {
            try
            {
                adObject.Properties["description"].Value = descriptionField;
                adObject.CommitChanges();
                adObject.Close();
            }
            catch (System.DirectoryServices.DirectoryServicesCOMException E)
            {
                MessageBox.Show(E.Message.ToString());
            }
        }

        //Set locationfield.
        private void setLocation(string locationField, DirectoryEntry adObject)
        {
            try
            {
                adObject.Properties["location"].Value = locationField;
                adObject.CommitChanges();
                adObject.Close();
            }
            catch (System.DirectoryServices.DirectoryServicesCOMException E)
            {
                MessageBox.Show(E.Message.ToString());
            }
        }

        // Add object to groups
        private bool addToGroup(string groupDn, DirectoryEntry adObject)
        {
            bool groupAdded = false;
            // Complete ldap path of computer object
            string objectPath = adObject.Path;
            string objectDN = adObject.Properties["distinguishedName"].Value.ToString();
            // Construct complete ldap of group, based on ldap path of computer object.
            // Including servername if used.
            string temp1 = objectPath.Replace(objectDN, "");
            string groupPath = temp1 + groupDn;
            // MessageBox.Show(groupPath + Environment.NewLine + objectDN);
            if (!isMemberOf(adObject, groupDn))
            {
                try
                {
                    DirectoryEntry dirEntry = new DirectoryEntry(groupPath);
                    dirEntry.Properties["member"].Add(objectDN);
                    dirEntry.CommitChanges();
                    dirEntry.Close();
                    groupAdded = true;
                }
                catch (System.DirectoryServices.DirectoryServicesCOMException E)
                {
                    MessageBox.Show(E.Message.ToString());
                }
            }
            return groupAdded;
        }

        // Check if user is member of group
        private bool isMemberOf(DirectoryEntry adObject, string groupDN)
        {
            bool ismember = false;
            try
            {
                PropertyValueCollection groups = adObject.Properties["memberOf"];
                foreach (string g in groups)
                {
                    // g contains Distinguishedname
                    if (g.Equals(groupDN))
                    {
                        ismember = true;
                    }
                }
            }
            catch (System.DirectoryServices.DirectoryServicesCOMException E)
            {
                MessageBox.Show(E.Message.ToString());
            }
            return ismember;
        }

        // read the domainlist from Config.xml and fill combobox comboBoxDomain.
        private void fillDomainListbox()
        {
            ArrayList items = new ArrayList();
            try
            {
                FileStream stream = new FileStream(configFile, FileMode.Open);
                XmlReader xmlReader = XmlReader.Create(stream);

                while (xmlReader.Read())
                {
                    if ((xmlReader.NodeType == XmlNodeType.Element) && (xmlReader.Name == "Domain"))
                    {
                        items.Add(xmlReader.GetAttribute("name"));
                    }
                }

                if (items.Count > 0)
                {
                    items.Sort();
                    this.comboBoxDomain.Items.AddRange(items.ToArray());
                    this.comboBoxDomain.SelectedIndex = 0;
                }
                stream.Close();
                xmlReader.Close();
            }

            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
        }

        // read the ldap path from Config.xml.
        // element should have name "Connection"
        // attibute should hava name ldapstring.
        private string ldapString(string domain)
        {
            string ldapPath = "";
            try
            {
                FileStream stream = new FileStream(configFile, FileMode.Open);
                XmlReader xmlReader = XmlReader.Create(stream);

                while (xmlReader.Read())
                {
                    if ((xmlReader.NodeType == XmlNodeType.Element) && (xmlReader.Name == "Domain"))
                    {
                        if (xmlReader.HasAttributes)
                        {
                            if (xmlReader.GetAttribute("name") == domain)
                            {
                                ldapPath = xmlReader.GetAttribute("ldapstring");
                            }
                        }
                    }
                }
                stream.Close();
                xmlReader.Close();
            }
            catch (Exception e)
            {
                MessageBox.Show(e.Message);
            }
            return ldapPath;
        }

        private void btnCopy_Click(object sender, EventArgs e)
        {
            copyAttributes();
        }

        private void aboutToolStripMenuItem1_Click(object sender, EventArgs e)
        {
            frmAboutbox frmAbout = new frmAboutbox();
            frmAbout.Show();
        }

        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            this.Close();
        }

    }
}
